import type { EQConfig } from './types'

export interface OpenUSBDevice {
  sendData: (data: BufferSource, reportId: number) => Promise<DataView | null>
  sendDataNoResp: (data: BufferSource, reportId: number) => Promise<DataView | null>
}

export interface DeviceConfig {
  // Flag for local preset
  localPreset: boolean
  // Preset EQs
  presetEQs?: EQConfig[]
  // product UUID From database
  productUUID: string
  // HID report ID
  reportId: number
  // PEQ index position
  peqIndex: number
}

export abstract class BaseDevice<T> {
  protected openDevice: OpenUSBDevice
  protected config: DeviceConfig

  constructor(openDevice: OpenUSBDevice, config: DeviceConfig) {
    this.openDevice = openDevice
    this.config = config
  }

  protected abstract readEQIndex(): Promise<number>
  protected abstract writeEQIndex(index: number): Promise<void>
  protected abstract readPEQData(): Promise<T>
  protected abstract writePEQData(data: T): Promise<void>

  public isLocalPreset(): boolean {
    return this.config.localPreset
  }

  public getPresetEQs(): EQConfig[] {
    return this.config.presetEQs || []
  }

  public getProductUUID(): string {
    return this.config.productUUID
  }

  public getReportId(): number {
    return this.config.reportId
  }

  public async getEQIndex(): Promise<number> {
    return await this.readEQIndex()
  }

  public async setEQIndex(index: number): Promise<void> {
    await this.writeEQIndex(index)
  }

  public async getPEQData(): Promise<T> {
    return await this.readPEQData()
  }

  public async setPEQData(data: T): Promise<void> {
    await this.writePEQData(data)
  }

  public async setPEQMode(): Promise<void> {
    await this.writeEQIndex(this.config.peqIndex)
  }

  public async isInPEQMode(): Promise<boolean> {
    const currentEqIndex = await this.readEQIndex()
    return currentEqIndex === this.config.peqIndex
  }
}
